home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP13.ZIP / PATRON / IDROPTGT.CPP < prev    next >
C/C++ Source or Header  |  1993-06-27  |  15KB  |  576 lines

  1. /*
  2.  * IDROPTGT.CPP
  3.  *
  4.  * Implementation of a DropTarget object for Patron,
  5.  *
  6.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Software Design Engineer
  9.  * Microsoft Systems Developer Relations
  10.  *
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "patron.h"
  17.  
  18.  
  19.  
  20. /*
  21.  * CDropTarget::CDropTarget
  22.  * CDropTarget::~CDropTarget
  23.  *
  24.  * Constructor Parameters:
  25.  *  pDoc            LPCPatronDoc of the window containing us.
  26.  */
  27.  
  28. CDropTarget::CDropTarget(LPCPatronDoc pDoc)
  29.     {
  30.     m_cRef=0;
  31.     m_pDoc=pDoc;
  32.  
  33.     m_pIDataObject=NULL;
  34.     return;
  35.     }
  36.  
  37.  
  38. CDropTarget::~CDropTarget(void)
  39.     {
  40.     return;
  41.     }
  42.  
  43.  
  44.  
  45.  
  46. /*
  47.  * CDropTarget::QueryInterface
  48.  * CDropTarget::AddRef
  49.  * CDropTarget::Release
  50.  *
  51.  * Purpose:
  52.  *  IUnknown members for CDropTarget object.
  53.  */
  54.  
  55. STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  56.     {
  57.     *ppv=NULL;
  58.  
  59.     //Any interface on this object is the object pointer.
  60.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropTarget))
  61.         *ppv=(LPVOID)this;
  62.  
  63.     /*
  64.      * If we actually assign an interface to ppv we need to AddRef it
  65.      * since we're returning a new pointer.
  66.      */
  67.     if (NULL!=*ppv)
  68.         {
  69.         ((LPUNKNOWN)*ppv)->AddRef();
  70.         return NOERROR;
  71.         }
  72.  
  73.     return ResultFromScode(E_NOINTERFACE);
  74.     }
  75.  
  76.  
  77. STDMETHODIMP_(ULONG) CDropTarget::AddRef(void)
  78.     {
  79.     return ++m_cRef;
  80.     }
  81.  
  82. STDMETHODIMP_(ULONG) CDropTarget::Release(void)
  83.     {
  84.     ULONG           cRefT;
  85.  
  86.     cRefT=--m_cRef;
  87.  
  88.     if (0L==m_cRef)
  89.         delete this;
  90.  
  91.     return cRefT;
  92.     }
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CDropTarget::DragEnter
  100.  *
  101.  * Purpose:
  102.  *  Indicates that data in a drag operation has been dragged over our
  103.  *  window that's a potential target.  We are to decide if it's something
  104.  *  we're interested in or not.
  105.  *
  106.  * Parameters:
  107.  *  pIDataSource    LPDATAOBJECT providing the source data.
  108.  *  grfKeyState     DWORD flags indicating states of keys and mouse buttons.
  109.  *  pt              POINTL coordinates in the client space of the document.
  110.  *  pdwEffect       LPDWORD into which we'll place the appropriate effect
  111.  *                  flag for this point.
  112.  *
  113.  * Return Value:
  114.  *  SCODE           NOERROR
  115.  */
  116.  
  117. STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pIDataSource
  118.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  119.     {
  120.     LPCPages        ppg=m_pDoc->m_pPG;
  121.     HWND            hWnd;
  122.     FORMATETC       fe;
  123.     STGMEDIUM       stm;
  124.     UINT            uRet;
  125.  
  126.     m_fFeedback=FALSE;
  127.     m_pIDataObject=NULL;
  128.  
  129.     if (!m_pDoc->FQueryPasteFromData(pIDataSource, &fe, NULL))
  130.         {
  131.         *pdwEffect=DROPEFFECT_NONE;
  132.         return NOERROR;
  133.         }
  134.  
  135.     //Check if we can link from this data object as well.
  136.     ppg->m_fLinkAllowed=SUCCEEDED(OleQueryLinkFromData(pIDataSource));
  137.  
  138.     //We never allow it dragging in ourselves.
  139.     ppg->m_fLinkAllowed &= !ppg->m_fDragSource;
  140.  
  141.     //Check if this is a valid drop point.
  142.     uRet=ppg->UTestDroppablePoint(&pt);
  143.     ppg->m_uLastTest=uRet;
  144.  
  145.     if (UDROP_NONE==uRet)
  146.         *pdwEffect=DROPEFFECT_NONE;
  147.     else
  148.         {
  149.         //Default is move if we can, in fact drop here.
  150.         *pdwEffect=DROPEFFECT_MOVE;
  151.  
  152.         if (grfKeyState & MK_CONTROL)
  153.             {
  154.             if (ppg->m_fLinkAllowed && (grfKeyState & MK_SHIFT))
  155.                 *pdwEffect=DROPEFFECT_LINK;
  156.             else
  157.                 *pdwEffect=DROPEFFECT_COPY;
  158.             }
  159.         }
  160.  
  161.     m_pIDataObject=pIDataSource;
  162.     m_pIDataObject->AddRef();
  163.  
  164.     /*
  165.      * Determine the size of the data, if we can.  The default is
  166.      * a small rectangle since we can't easily tell what size something
  167.      * will be if we're pulling in a metafile or bitmap.  It's not
  168.      * a good idea to render it here with ::GetData just to find that out.
  169.      * We only know the size if it's our own object in which case a
  170.      * ::GetData will be fast.
  171.      */
  172.  
  173.     if (fe.cfFormat==m_pDoc->m_cf)
  174.         {
  175.         if (SUCCEEDED(pIDataSource->GetData(&fe, &stm)))
  176.             {
  177.             LPPATRONOBJECT  ppo;
  178.             RECT            rc;
  179.  
  180.             ppo=(LPPATRONOBJECT)GlobalLock(stm.hGlobal);
  181.  
  182.             SetRect(&rc, (int)ppo->szl.cx, -(int)ppo->szl.cy, 0, 0);
  183.             RectConvertMappings(&rc, NULL, TRUE);
  184.             SETSIZEL(m_szl, rc.left, rc.top);
  185.  
  186.             m_ptPick=ppo->ptlPick;
  187.             m_fe=ppo->fe;
  188.  
  189.             GlobalUnlock(stm.hGlobal);
  190.             ReleaseStgMedium(&stm);
  191.             }
  192.         }
  193.     else
  194.         {
  195.         SETSIZEL(m_szl, 30, 30);
  196.         m_ptPick.x=0;
  197.         m_ptPick.y=0;
  198.         m_fe.cfFormat=0;
  199.  
  200.         /*
  201.          * Try to get CF_OBJECTDESCRIPTOR which might have a size and
  202.          * a pick point.  If it exists, then always use the point but
  203.          * still default to a 30*30 size if the sizes are zero.
  204.          */
  205.         uRet=RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  206.         SETDefFormatEtc(fe, uRet, TYMED_HGLOBAL);
  207.  
  208.         if (SUCCEEDED(pIDataSource->GetData(&fe, &stm)))
  209.             {
  210.             LPOBJECTDESCRIPTOR  pOD;
  211.  
  212.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  213.  
  214.             //Get the size, converting to LOMETRIC.
  215.             if (0!=pOD->sizel.cx && 0!=pOD->sizel.cy)
  216.                 XformSizeInHimetricToPixels(NULL, &pOD->sizel, &m_szl);
  217.  
  218.             //POINTL and SIZEL are interchangeable
  219.             XformSizeInHimetricToPixels(NULL, (LPSIZEL)&pOD->pointl
  220.                 , (LPSIZEL)&m_ptPick);
  221.  
  222.             GlobalUnlock(stm.hGlobal);
  223.             ReleaseStgMedium(&stm);
  224.             }
  225.         }
  226.  
  227.  
  228.     //Bring the document window up front and show what a drop will do.
  229.     hWnd=m_pDoc->Window();
  230.     BringWindowToTop(hWnd);
  231.     UpdateWindow(hWnd);
  232.  
  233.     ppg->m_uVScrollCode=0xFFFF;
  234.     ppg->m_uHScrollCode=0xFFFF;
  235.     m_fPendingRepaint=FALSE;
  236.  
  237.     pt.x-=m_ptPick.x;
  238.     pt.y-=m_ptPick.y;
  239.  
  240.     m_ptLast=pt;
  241.     m_fFeedback=TRUE;
  242.     ppg->DrawDropTargetRect(&pt, &m_szl);
  243.  
  244.     return NOERROR;
  245.     }
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252. /*
  253.  * CDropTarget::DragOver
  254.  *
  255.  * Purpose:
  256.  *  Indicates that the mouse was moved inside the window represented
  257.  *  by this drop target.  This happens on every WM_MOUSEMOVE, so this
  258.  *  function should be very efficient.
  259.  *
  260.  * Parameters:
  261.  *  grfKeyState     DWORD providing the current keyboard and mouse states
  262.  *  pt              POINTL where the mouse currently is.
  263.  *  pdwEffect       LPDWORD in which to store the effect flag for this point.
  264.  *
  265.  * Return Value:
  266.  *  SCODE           NOERROR
  267.  */
  268.  
  269. STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt
  270.     , LPDWORD pdwEffect)
  271.     {
  272.     LPCPages    ppg=m_pDoc->m_pPG;
  273.     UINT        uRet, uLast;
  274.     UINT        xPos, yPos;
  275.  
  276.     if (NULL==m_pIDataObject)
  277.         return NOERROR;
  278.  
  279.     //Check if this is still a valid point.  uRet is used below as well.
  280.     uRet=ppg->UTestDroppablePoint(&pt);
  281.  
  282.     if (UDROP_NONE==uRet)
  283.         *pdwEffect=DROPEFFECT_NONE;
  284.     else
  285.         {
  286.         //Store these before possibly ORing in DROPEFFECT_SCROLL
  287.         *pdwEffect=DROPEFFECT_MOVE;
  288.  
  289.         if (grfKeyState & MK_CONTROL)
  290.             {
  291.             if (ppg->m_fLinkAllowed && (grfKeyState & MK_SHIFT))
  292.                 *pdwEffect=DROPEFFECT_LINK;
  293.             else
  294.                 *pdwEffect=DROPEFFECT_COPY;
  295.             }
  296.         }
  297.  
  298.     //If we haven't moved and we are not scrolling, then we're done.
  299.     if ((pt.x-m_ptPick.x==m_ptLast.x) && (pt.y-m_ptPick.y==m_ptLast.y)
  300.         && !((UDROP_INSETHORZ | UDROP_INSETVERT) & ppg->m_uLastTest))
  301.         {
  302.         return NOERROR;
  303.         }
  304.  
  305.     //Remove the last feedback rectangle.
  306.     if (m_fFeedback)
  307.         ppg->DrawDropTargetRect(&m_ptLast, &m_szl);
  308.  
  309.     uLast=ppg->m_uLastTest;
  310.     ppg->m_uLastTest=uRet;
  311.  
  312.     if (UDROP_NONE==uRet)
  313.         {
  314.         //If we are now an invalid point, better repaint as necessary
  315.         if (m_fPendingRepaint)
  316.             {
  317.             UpdateWindow(ppg->m_hWnd);
  318.